#!/usr/bin/env python
# -*- coding: utf-8; -*-

from django.shortcuts import render, redirect
from django.urls import reverse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

from web.forms.wiki import WikiModelForm
from web import models
from utils.encrypt import uid
from utils.tencent.cos import upload_file


def wiki(request, project_id):
    """显示 Wiki 标题

    1. 若URL中携带有效wiki_id，页面显示左侧为项目wiki目录，右侧wiki内容，且
       显示“新建””编辑““删除”三个操作按钮
    2. 若URL中wiki_id无效或缺失，页面左侧为项目wiki目录，右侧只显示“新建”按钮，且
       内容区域提示当前项目名称 + 另一个新建wiki 的按钮
    """
    wiki_id = request.GET.get('wiki_id')

    # 未指定wiki的ID时，渲染项目wiki展示页面
    if not wiki_id or not wiki_id.isdecimal():
        return render(request, 'web/wiki.html')

    wiki_obj = models.Wiki.objects.filter(id=wiki_id,
                                          project_id=project_id).first()
    print(wiki_obj)

    # 注意 wiki_obj 为模型类对象，并不是表单类对象
    return render(request, 'web/wiki.html', {'wiki_object': wiki_obj})


def wiki_add(request, project_id):
    """ wiki添加 """
    if request.method == 'GET':
        form = WikiModelForm(request)
        return render(request, 'web/wiki_add.html', {'form': form})

    # 参数不可以写错了，第一个是 request，第二个才是post表单携带的数据
    form = WikiModelForm(request, data=request.POST)
    if form.is_valid():
        # 是否已选择父文章
        if form.instance.parent:
            form.instance.depth = form.instance.parent.depth + 1
        else:
            form.instance.depth = 1
        # 固定表单中的项目
        form.instance.project = request.tracer.project
        form.save()
        url = reverse('wiki', kwargs={'project_id': project_id})
        return redirect(url)

    return render(request, 'web/wiki_add.html', {'form': form})


def wiki_catalog(request, project_id):
    """ wiki目录 """

    # 获取当前项目所有的目录: data = QuerySet类型
    # data = models.Wiki.objects.filter(
    #     project=request.tracer.project).values_list("id", 'title', 'parent_id')
    #
    # 使用 values 方法(而不是 values_list 方法)，使得返回的QuerySet结果中每
    # 个元素的类型是字典(而不是元组)
    data = models.Wiki.objects.filter(project=request.tracer.project).values(
        "id", 'title', 'parent_id').order_by('depth', 'id')

    # 将 data 转化为列表类型，因为QuerySet类型无法被 JsonResponse 序列化
    return JsonResponse({'status': True, 'data': list(data)})


def wiki_delete(request, project_id, wiki_id):
    """删除文章"""

    # 删除文章，需要点击删除按钮，或者在地址栏输入类似
    # /manage/6/wiki/delete/10/ 的地址

    # 额外注意，在模板文件内的 url 标签记得确认参数是否完整，避免 reverse 错误

    models.Wiki.objects.filter(project_id=project_id, id=wiki_id).delete()
    fallback_url = reverse('wiki', kwargs={'project_id': project_id})
    # print("url ----- > {}".format(fallback_url))
    #     => /manage/6/wiki/  (主wiki页面)
    return redirect(fallback_url)


def wiki_edit(request, project_id, wiki_id):
    """ wiki编辑 """
    wiki_obj = models.Wiki.objects.filter(id=wiki_id,
                                          project_id=project_id).first()
    if not wiki_obj:
        url = reverse('wiki', kwargs={'project_id': project_id})
        return redirect(url)

    # 编辑页面与添加页面基本相同，除了需要在表单中显示wiki对象的内容、标题等
    # 所以相比新建，多一个参数 instance 传入即可
    if request.method == 'GET':
        form = WikiModelForm(request, instance=wiki_obj)
        return render(request, 'web/wiki_form.html', {'form': form})

    # 参数不可以写错了，第一个是 request，第二个才是post表单携带的数据
    form = WikiModelForm(request, data=request.POST, instance=wiki_obj)
    if form.is_valid():
        # 是否已选择父文章
        if form.instance.parent:
            form.instance.depth = form.instance.parent.depth + 1
        else:
            form.instance.depth = 1
        # 固定表单中的项目
        form.instance.project = request.tracer.project
        form.save()
        url = reverse('wiki', kwargs={'project_id': project_id})
        preview_url = "{0}?wiki_id={1}".format(url, wiki_id)
        return redirect(preview_url)

    return render(request, 'web/wiki_form.html', {'form': form})


# wiki编辑或新建时，用户有上传图片的需求，添加wiki_upload视图和url负责这一
# 部分。markdown编辑器负责发送该(post)请求，需要设置
# 1. 是否允许本地图片上传
# 2. 支持的图片格式
# 3. post请求发送的目标地址(django后端依项目传给前端该地址，可使用模板渲染后
#    固定到前端页面的markdown编辑器配置中)
# 因此，
# 1. markdown 部分：创建 markdown 编辑器时设置选项
#    ``` js
#    var WIKI_UPLOAD_URL = "{% url 'wiki_upload' project_id=request.tracer.project.id %}"
#    #
#    function initEditorMd() {
#        editormd('id_editor', {
#           // ... other config ...
#           imageUpload: true,
#           imageFormats:['jpeg','png','gif'],
#           imageUploadURL:WIKI_UPLOAD_URL,
#        })
#    }
#    ```
# 2. django 部分：处理WIKI_UPLOAD_URL对应的请求, 且markdown编辑器中的上传路径
#    由django模板引擎渲染得到，固定在前端页面中

# 第一版：使用 python 上传图片逻辑
#
# 1. markdown 编辑器开启本地上传功能
# 2. 编辑器点击上传按钮后发送 wiki_upload 请求，请求的地址在后端页面渲染时已
#    固定，请求会发送图片文件
# 3. django 接受该文件对象，调用 cos.py 中的 upload_file 函数处理进行上传到项
#    目对应的桶内
# 4. cos 桶返回文件保存的路径(见 cos.upload_file return 语句)
# 5. django 接受图片的路径，返回给markdown编辑器
# 6. markdown编辑器结束上传会话
#
# 注意：前端的markDOWN编辑器只有收到django后台的反馈信息后，才会结束上传会话，
# 否则一直显示为上传中

# 对该请求忽略csrf_token认证
@csrf_exempt
def wiki_upload(request, project_id):
    """ 负责markdown编辑器上传图片请求 """
    result = {'success': 0, 'message': None, 'url': None}

    # 接受markdown编辑器发送过来的文件对象
    image_object = request.FILES.get('editormd-image-file')
    if not image_object:
        result['message'] = "文件不存在"
        return JsonResponse(result)

    ext = image_object.name.rsplit('.')[-1]
    key = "{name}.{ext}".format(name=uid(request.tracer.user.phone), ext=ext)
    image_url = upload_file(request.tracer.project.bucket,
                            request.tracer.project.region,
                            image_object,
                            key)
    result['success'] = 1
    result['url'] = image_url

    return JsonResponse(result)
